﻿//==============================================================================  
//Copyright (C) 2012-2015 9UN.ORG. All rights reserved. 
//GUID：b2096c56-e0c2-490e-bbba-2242446de6cc
//CLR Version: 4.0.30319.18033
//Code Author：Kevin Wang
//Contact：Email(Admin@9un.org),QQ(265382 or 74344)
//Filename：MatchContentType
//Namespace：RuanRang.Core.Utility
//Functions：MatchContentType  
//Created by Kevin Wang at 2013/2/4 20:33:26 http://blog.9un.org
//============================================================================== 

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace RuanRang.Core.Utility
{
    public class FullScreenHelper
    {
        /// <summary>
        /// The _win state
        /// </summary>
        private FormWindowState _winState;
        /// <summary>
        /// The _BRD style
        /// </summary>
        private FormBorderStyle _brdStyle;
        /// <summary>
        /// The _top most
        /// </summary>
        private bool _topMost;
        /// <summary>
        /// The _bounds
        /// </summary>
        private Rectangle _bounds;
        /// <summary>
        /// The _mouse handler
        /// </summary>
        private readonly GlobalMouseHandler _mouseHandler;
        /// <summary>
        /// Gets the system metrics.
        /// </summary>
        /// <param name="which">The which.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
        public static extern int GetSystemMetrics(int which);

        /// <summary>
        /// Sets the window pos.
        /// </summary>
        /// <param name="hwnd">The HWND.</param>
        /// <param name="hwndInsertAfter">The HWND insert after.</param>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="flags">The flags.</param>
        [DllImport("user32.dll")]
        public static extern void SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,int x, int y, int width, int height, uint flags);

        /// <summary>
        /// The S m_ CXSCREEN
        /// </summary>
        private const int SmCxscreen = 0;

        /// <summary>
        /// The S m_ CYSCREEN
        /// </summary>
        private const int SmCyscreen = 1;

        /// <summary>
        /// The HWND top
        /// </summary>
        private static readonly IntPtr HwndTop = IntPtr.Zero;

        /// <summary>
        /// The SW p_ SHOWWINDOW
        /// </summary>
        private const int SwpShowwindow = 64; // 0x0040

        /// <summary>
        /// Gets the screen X.
        /// </summary>
        /// <value>The screen X.</value>
        public static int ScreenX
        {
            get { return GetSystemMetrics(SmCxscreen); }
        }

        /// <summary>
        /// Gets the screen Y.
        /// </summary>
        /// <value>The screen Y.</value>
        public static int ScreenY
        {
            get { return GetSystemMetrics(SmCyscreen); }
        }

        /// <summary>
        /// Sets the win full screen.
        /// </summary>
        /// <param name="hwnd">The HWND.</param>
        public static void SetWinFullScreen(IntPtr hwnd)
        {
            SetWindowPos(hwnd, HwndTop, 0, 0, ScreenX, ScreenY, SwpShowwindow);
        }

        /// <summary>
        /// Gets or sets the hot rectangle.
        /// </summary>
        /// <value>The hot rectangle.</value>
        public Rectangle HotRectangle
        {
            get { return _mouseHandler.HotRectangle; }
            set { _mouseHandler.HotRectangle = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [enable mouse hide].
        /// </summary>
        /// <value><c>true</c> if [enable mouse hide]; otherwise, <c>false</c>.</value>
        public bool EnableMouseHide { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether this instance is mouse hided.
        /// </summary>
        /// <value><c>true</c> if this instance is mouse hided; otherwise, <c>false</c>.</value>
        public bool IsMouseHided { get; set; }
        /// <summary>
        /// Occurs when [mouse move to hot rectangle event].
        /// </summary>
        public event GlobalMouseHandler.MouseMoveHander MouseMoveToHotRectangleEvent;
        /// <summary>
        /// Occurs when [mouse leave from hot rectangle event].
        /// </summary>
        public event GlobalMouseHandler.MouseMoveHander MouseLeaveFromHotRectangleEvent;

        /// <summary>
        /// Raises the <see>
        ///                <cref>E:MouseLeaveFromHotRectangleEvent</cref>
        ///            </see>
        ///     event.
        /// </summary>
        /// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        public void OnMouseLeaveFromHotRectangleEvent(MouseEventArgs args)
        {
            var handler = MouseLeaveFromHotRectangleEvent;
            if (handler != null) handler(this, args);
        }

        /// <summary>
        /// Raises the <see>
        ///              <cref>E:MouseMoveToHotRectangle</cref>
        ///            </see>  event.
        /// </summary>
        /// <param name="args">The <see cref="MouseEventArgs" /> instance containing the event data.</param>
        public void OnMouseMoveToHotRectangle(MouseEventArgs args)
        {
            var handler = MouseMoveToHotRectangleEvent;
            if (handler != null) handler(this, args);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="FullScreenHelper" /> class.
        /// </summary>
        public FullScreenHelper()
        {
            IsFullScreen = false;
            EnableMouseHide = true;
            _mouseHandler = new GlobalMouseHandler();
            _mouseHandler.MouseMoveEvent += MouseMoveEnvent;
            _mouseHandler.MouseMoveToHotRectangleEvent += MouseHandlerOnMouseMoveToHotRectangle;
            _mouseHandler.MouseStoppedEvent += MouseHandlerOnMouseStoppedEvent;
            _mouseHandler.MouseLeaveFromHotRectangleEvent += MouseHandlerOnMouseLeaveFromHotRectangle;
        }

        /// <summary>
        /// Mouses the handler on mouse stopped event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        private void MouseHandlerOnMouseStoppedEvent(object sender, MouseEventArgs args)
        {
            if (!IsFullScreen)
            {
                return;
            }
            if (!EnableMouseHide)
            {
                return;
            }
            if (IsMouseHided)
            {
                return;
            }
            GlobalMouseHandler.ShowCursor(0);
            IsMouseHided = true;
        }

        /// <summary>
        /// Mouses the handler on mouse move to hot rectangle.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        private void MouseHandlerOnMouseMoveToHotRectangle(object sender, MouseEventArgs args)
        {
            if (!IsFullScreen)
            {
                return;
            }
            OnMouseMoveToHotRectangle(args);
        }

        /// <summary>
        /// Mouses the handler on mouse leave from hot rectangle.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        private void MouseHandlerOnMouseLeaveFromHotRectangle(object sender, MouseEventArgs args)
        {
            if (!IsFullScreen)
            {
                return;
            }
            OnMouseLeaveFromHotRectangleEvent(args);
        }

        /// <summary>
        /// Mouses the move envent.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        private void MouseMoveEnvent(object sender, MouseEventArgs args)
        {
            if (!IsFullScreen)
            {
                return;
            }
            if (!IsMouseHided) return;
            GlobalMouseHandler.ShowCursor(1);
            IsMouseHided = false;
        }

        /// <summary>
       /// Gets or sets a value indicating whether this instance is full screen.
       /// </summary>
       /// <value><c>true</c> if this instance is full screen; otherwise, <c>false</c>.</value>
        public bool IsFullScreen
        {
            get;
            set;
        }

        /// <summary>
        /// Maximize the window to the full screen.
        /// </summary>
        /// <param name="targetForm">The target form.</param>
        public void Enter(Form targetForm)
        {
            if (IsFullScreen) return;
            Save(targetForm);  // Save the original form state.

            targetForm.WindowState = FormWindowState.Maximized;
            targetForm.FormBorderStyle = FormBorderStyle.None;
            targetForm.TopMost = true;
            targetForm.Bounds = Screen.GetBounds(targetForm);
            SetWinFullScreen(targetForm.Handle);
            IsFullScreen = true;
        }

        /// <summary>
        /// Save the current Window state.
        /// </summary>
        /// <param name="targetForm">The target form.</param>
        private void Save(Form targetForm)
        {
            _winState = targetForm.WindowState;
            _brdStyle = targetForm.FormBorderStyle;
            _topMost = targetForm.TopMost;
            _bounds = targetForm.Bounds;
        }

        /// <summary>
        /// Leave the full screen mode and restore the original window state.
        /// </summary>
        /// <param name="targetForm">The target form.</param>
        public void Leave(Form targetForm)
        {
            if (!IsFullScreen) return;
            // Restore the original Window state.
            targetForm.WindowState = _winState;
            targetForm.FormBorderStyle = _brdStyle;
            targetForm.TopMost = _topMost;
            targetForm.Bounds = _bounds;
            IsFullScreen = false;
            if (!IsMouseHided) return;
            GlobalMouseHandler.ShowCursor(1);
            IsMouseHided = false;
        }
    }
}
